﻿using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Project2004.Jigsaw.Models;
using Project2004.Jigsaw.Presenters;
using Project2004.Jigsaw.Utils;
using System;

namespace Project2004.Jigsaw.Controls;

public partial class JigsawBlock2 : UserControl
{
    #region statics

    private static Bitmap TestBitmap { get; set; }

    static JigsawBlock2()
    {
        var imagePath = System.IO.Path.Combine(Environment.CurrentDirectory, "Assets", "test.png");
        TestBitmap = new Bitmap(imagePath);

    }

    #endregion

    #region props

    /// <summary>
    /// JigsawConfig StyledProperty definition
    /// </summary>
    public static readonly StyledProperty<JigsawConfig> JigsawConfigProperty =
        AvaloniaProperty.Register<JigsawBlock2, JigsawConfig>(nameof(JigsawConfig), JigsawConfig.Parse("In,In,In,In"));

    /// <summary>
    /// Gets or sets the JigsawConfig property. This StyledProperty
    /// indicates ....
    /// </summary>
    public JigsawConfig JigsawConfig
    {
        get => this.GetValue(JigsawConfigProperty);
        set => SetValue(JigsawConfigProperty, value);
    }

    #endregion

    #region props

    public BlockId Id => _block.Id;
    public Block Block => _block;

    #endregion

    #region fields

    private IJigsawShapeData _data;
    private Path _path;
    private Bitmap _bitmapSource;
    private Scene _scene;
    private Block _block;
    internal BlockPresenter Presenter;

    public IJigsawShapeData Data => _data;


    #endregion

    #region ctors
    public JigsawBlock2() : this(null!, null!, null!)
    {

    }

    public JigsawBlock2(Bitmap bitmapSource, Scene scene, Block block)
    {
        InitializeComponent();

        _bitmapSource = bitmapSource ?? TestBitmap;
        _scene = scene ?? new Scene(_bitmapSource.PixelSize.Width, _bitmapSource.PixelSize.Height, 1, 1);

        _block = block ?? new Block(new BlockId(0, 0), 0, 0);

        JigsawConfig = _block.JigsawConfig;

        var boundSize = FullConfigJigsawShapeData.GetBoundSizeFromBorderLen(_scene.Size);
        Width = boundSize;
        Height = boundSize;

    }

    #endregion

    #region overrides

    protected override void OnLoaded(RoutedEventArgs e)
    {
        base.OnLoaded(e);

        var data = new FullConfigJigsawShapeData(Math.Min(Bounds.Width, Bounds.Height), JigsawConfig);
        _data = data;
        _path = CreateFromJigsawShapeData(data);

        PART_Canvas.Children.Add(_path);
    }

    protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
    {
        base.OnPropertyChanged(change);

        if (change.Property == JigsawConfigProperty)
        {
            var newValue = (JigsawConfig)change.NewValue!;
            _block.JigsawConfig = newValue;
            PART_Canvas.Children.Remove(_path);

            var data = new FullConfigJigsawShapeData(Math.Min(Bounds.Width, Bounds.Height), newValue);
            _data = data;
            _path = CreateFromJigsawShapeData(data);

            PART_Canvas.Children.Add(_path);
        }
    }
    #endregion

    #region methods
    private Ellipse CreatePoint(Point point)
    {
        var size = 5;
        var shape = new Ellipse() { Fill = Brushes.Red, Width = size, Height = size };
        Canvas.SetLeft(shape, point.X - size / 2);
        Canvas.SetTop(shape, point.Y - size / 2);

        return shape;
    }

    [Obsolete("纯测试用的")]
    private Path CreateArcPath(Point start, Point end, Size size, double angle)
    {
        var path = new Path();

        var pathGeometry = new PathGeometry();
        var figure = new PathFigure();

        figure.IsClosed = false;
        figure.StartPoint = start;
        figure.Segments.Add(new ArcSegment() { IsLargeArc = true, Point = end, Size = size, RotationAngle = angle });

        pathGeometry.Figures.Add(figure);

        path.Data = pathGeometry;

        path.StrokeThickness = 2;
        path.Stroke = Brushes.Aqua;
        return path;
    }

    [Obsolete("纯测试用的")]
    private Path CreateArcPathU(Point start, Point end, Size size, double angle)
    {
        var path = new Path();

        var pathGeometry = new PathGeometry();
        var figure = new PathFigure();

        figure.IsClosed = false;
        figure.StartPoint = start;
        figure.Segments.Add(new ArcSegment() { IsLargeArc = false, Point = end, Size = size, RotationAngle = angle, SweepDirection = SweepDirection.CounterClockwise });

        pathGeometry.Figures.Add(figure);

        path.Data = pathGeometry;

        path.StrokeThickness = 2;
        path.Stroke = Brushes.Aqua;
        return path;
    }

    [Obsolete("纯测试用的")]
    private Path CreateArcPathUEx(Point start, Point end, Size size, double angle)
    {
        var path = new Path();

        var pathGeometry = new PathGeometry();
        var figure = new PathFigure();

        figure.IsClosed = false;
        figure.StartPoint = start;
        figure.Segments.Add(new ArcSegment() { IsLargeArc = true, Point = end, Size = size, RotationAngle = angle, SweepDirection = SweepDirection.Clockwise });

        pathGeometry.Figures.Add(figure);

        path.Data = pathGeometry;

        path.StrokeThickness = 2;
        path.Stroke = Brushes.Aqua;
        return path;
    }

    /// <summary>
    /// 进行轮廓的创建，并且填充上对应的图像。
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private Path CreateFromJigsawShapeData(IJigsawShapeData data)
    {
        var path = new Path();

        var pathGeometry = new PathGeometry();
        var figure = new PathFigure();
        figure.IsClosed = true;
        figure.StartPoint = data.StartPoint;

        for (int i = 0; i < data.JigsawPoints.Count - 1; i++)
        {
            var segment = CreateSegmentFromJigsawShapeData(data, i);
            if (segment is null) throw new NotImplementedException();

            figure!.Segments!.Add(segment);
        }

        pathGeometry!.Figures!.Add(figure);
        path.Data = pathGeometry;

        path.StrokeThickness = 2;
        path.Stroke = Brushes.Aqua;

        //path.Fill = Brushes.Black;
        //var uri = @"C:\Users\fan.lai\Pictures\OIP-C.jpg";

        var sourceRect = _block.GetImageSourceRect(_scene.Size);

        path.Fill = new ImageBrush()
        {
            Source = _bitmapSource,
            SourceRect = new RelativeRect(sourceRect, RelativeUnit.Absolute),
            AlignmentX = AlignmentX.Left,
            AlignmentY = AlignmentY.Top,
            Stretch = Stretch.None
        };

        return path;
    }

    private PathSegment CreateSegmentFromJigsawShapeData(IJigsawShapeData data, int index)
    {
        if (index < 0) return null;
        if (index >= data.JigsawPoints.Count) return null;
        var jigsawPoint1 = data.JigsawPoints[index];
        var jigsawPoint2 = data.JigsawPoints[index + 1];

        if (jigsawPoint1.Type == JigsawPointType.Line)
        {
            return new LineSegment() { Point = jigsawPoint2.Point };
        }
        else if (jigsawPoint1.Type == JigsawPointType.Arc)
        {
            return new ArcSegment()
            {
                IsLargeArc = jigsawPoint1.IsLargeArc,
                Point = jigsawPoint2.Point,
                Size = jigsawPoint1.Size,
                SweepDirection = jigsawPoint1.SweepDirection,
                RotationAngle = jigsawPoint1.ArcAngle
            };
        }
        return null;
    }
    #endregion



}

